﻿using System;
using System.Data.SqlClient;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Modules._2DoTasks.Components.Entities;
using DotNetNuke.Modules._2DoTasks.Components.ExceptionHandling;
using DotNetNuke.Modules._2DoTasks.Components.Interfaces;
using DotNetNuke.Modules._2DoTasks.Data;

namespace DotNetNuke.Modules._2DoTasks.Components.Controllers
{
    /// <summary>
    /// Controller object with business logic for TaskSubTasks
    /// </summary>
    public class TaskSubTaskController : IRepository<_TaskSubTask, int>
    {
        private UnitOfWork _uof;
        private int _taskId;

        #region IRepository<_TaskSubTask> Members

        public TaskSubTaskController(UnitOfWork uof, int taskId)
        {
            _uof = uof;
            this._taskId = taskId;
        }

        /// <summary>
        /// Gets the TaskSubTask with the passed id
        /// </summary>
        /// <param name="TaskSubTaskId">the TaskSubTask id</param>
        /// <param name="additionalFields">not used in TaskSubTask entity</param>
        /// <returns>returns a TaskSubTask object</returns>
        public _TaskSubTask Get(int TaskSubTaskId, params object[] additionalFields)
        {
            return CBO.FillObject<_TaskSubTask>(DataProvider.Instance().GetTaskSubTask(TaskSubTaskId, this._taskId, this._uof.PortalId, this._uof.CurrentUser.UserID));
        }

        /// <summary>
        /// Returns all TaskSubTasks
        /// </summary>
        /// <returns>retuns list of TaskSubTasks</returns>
        public System.Collections.Generic.List<_TaskSubTask> GetAll()
        {
            return CBO.FillCollection<_TaskSubTask>(DataProvider.Instance().GetAllTaskSubTaskEntries(this._taskId, this._uof.PortalId, this._uof.CurrentUser.UserID));
        }

        /// <summary>
        /// Sets the task has completed, or not depending on completion date
        /// </summary>
        /// <param name="entity">the task to update</param>
        public void ToggleComplete(_TaskSubTask entity)
        {
            if (entity.CompletionDate.HasValue)
                entity.CompletionDate = null;
            else
                entity.CompletionDate = DateTime.Now;
            Update(entity);
        }

        /// <summary>
        /// Adds a new entity
        /// </summary>
        /// <param name="entity">entity to create</param>
        public void Add(_TaskSubTask entity)
        {
            try
            {
                entity.ParentTaskId = this._taskId;
                entity.CreationUserId = this._uof.CurrentUser.UserID;
                entity.ModuleID = this._uof.ModuleId;
                entity.Id = DataProvider.Instance().Add(entity, this._uof.PortalId);
            }
            catch (SqlException exc)
            {
                if (exc.Message.Contains("fk_STsk_ParentTaskId"))
                    throw new TaskSubTaskValidationException("Task not found.",
                        SharedEnum.CrudState.Insert,
                        (int)InsertStatus.TASKNOTFOUND);

                if (exc.Message.Contains("CREATORNOTMEMBER"))
                    throw new TaskSubTaskValidationException("The user is not a member of the project.",
                        SharedEnum.CrudState.Insert,
                        (int)InsertStatus.CREATORNOTMEMBER);

                if (exc.Message.Contains("ASSIGNEDNOTMEMBER"))
                    throw new TaskSubTaskValidationException("The user assigned is not a member of the project.",
                        SharedEnum.CrudState.Insert,
                        (int)InsertStatus.ASSIGNEDNOTMEMBER);

                if (exc.Message.Contains("INVALIDCREATIONUSER"))
                    throw new TaskSubTaskValidationException("The creation user must be the same user that created the task.",
                        SharedEnum.CrudState.Insert,
                        (int)InsertStatus.INVALIDCREATIONUSER);

                if (exc.Message.Contains("INVALIDASSIGNEDUSER"))
                    throw new TaskSubTaskValidationException("The assigned user must be the same user that created the task.",
                        SharedEnum.CrudState.Insert,
                        (int)InsertStatus.INVALIDASSIGNEDUSER);

                if (exc.Message.Contains("ck_TDT_Task_SubTaskValidFields"))
                    throw new TaskSubTaskValidationException("The user is not a member of the project.",
                        SharedEnum.CrudState.Insert,
                        (int)InsertStatus.SUBTASKNOTVALID);

                throw exc;
            }
        }

        /// <summary>
        /// Updates a TaskSubTask
        /// </summary>
        /// <param name="entity">TaskSubTask to update</param>
        public void Update(_TaskSubTask entity)
        {
            try
            {
                entity.ParentTaskId = this._taskId;
                entity.LastChangeUserId = this._uof.CurrentUser.UserID;
                entity.ModuleID = this._uof.ModuleId;

                DataProvider.Instance().Update(entity, this._uof.PortalId);
            }
            catch (SqlException exc)
            {
                if (exc.Message.Contains("fk_STsk_ParentTaskId"))
                    throw new TaskSubTaskValidationException("Task not found.",
                        SharedEnum.CrudState.Update,
                        (int)UpdateStatus.TASKNOTFOUND);

                if (exc.Message.Contains("ONLYCREATORCANCHANGE"))
                    throw new TaskSubTaskValidationException("Only the user that created the task can change it.",
                        SharedEnum.CrudState.Update,
                        (int)UpdateStatus.ONLYCREATORCANCHANGE);

                if (exc.Message.Contains("ASSIGNEDNOTMEMBER"))
                    throw new TaskSubTaskValidationException("The assigned user is not a member in the project.",
                        SharedEnum.CrudState.Update,
                        (int)UpdateStatus.ASSIGNEDNOTMEMBER);

                if (exc.Message.Contains("LASTCHANGEUSERNOTMEMBER"))
                    throw new TaskSubTaskValidationException("The user is not a member in the project.",
                        SharedEnum.CrudState.Update,
                        (int)UpdateStatus.LASTCHANGEUSERNOTMEMBER);

                if (exc.Message.Contains("ck_TDT_Task_SubTaskValidFields"))
                    throw new TaskSubTaskValidationException("The user is not a member of the project.",
                        SharedEnum.CrudState.Update,
                        (int)UpdateStatus.SUBTASKNOTVALID);

                throw exc;
            }
        }

        /// <summary>
        /// Updates a TaskSubTask order
        /// </summary>
        /// <param name="entity">TaskSubTask to update</param>
        /// <param name="newOrder">the new order value</param>
        /// <param name="increasedOrderPosition">true if new order is greater than previous value</param>
        public void UpdateOrder(_TaskSubTask entity, int newOrder)
        {
            try
            {
                entity.ParentTaskId = this._taskId;
                entity.LastChangeUserId = this._uof.CurrentUser.UserID;
                entity.ModuleID = this._uof.ModuleId;
                entity.Order = newOrder;

                DataProvider.Instance().UpdateOrder(entity, this._uof.PortalId, newOrder);
            }
            catch (SqlException exc)
            {
                if (exc.Message.Contains("fk_STsk_ParentTaskId"))
                    throw new TaskSubTaskValidationException("Task not found.",
                        SharedEnum.CrudState.Update,
                        (int)UpdateStatus.TASKNOTFOUND);

                if (exc.Message.Contains("ONLYCREATORCANCHANGE"))
                    throw new TaskSubTaskValidationException("Only the user that created the task can change it.",
                        SharedEnum.CrudState.Update,
                        (int)UpdateStatus.ONLYCREATORCANCHANGE);

                if (exc.Message.Contains("LASTCHANGEUSERNOTMEMBER"))
                    throw new TaskSubTaskValidationException("The user is not a member in the project.",
                        SharedEnum.CrudState.Update,
                        (int)UpdateStatus.LASTCHANGEUSERNOTMEMBER);

                if (exc.Message.Contains("ck_TDT_Task_SubTaskValidFields"))
                    throw new TaskSubTaskValidationException("The user is not a member of the project.",
                        SharedEnum.CrudState.Update,
                        (int)UpdateStatus.SUBTASKNOTVALID);

                throw exc;
            }
        }

        /// <summary>
        /// Deletes an existing TaskSubTask
        /// </summary>
        /// <param name="entity">TaskSubTask to delete</param>
        public void Delete(_TaskSubTask entity)
        {
            try
            {
                entity.ParentTaskId = this._taskId;
                entity.ModuleID = this._uof.ModuleId;
                DataProvider.Instance().Delete(entity, this._uof.PortalId, this._uof.CurrentUser.UserID);
            }
            catch (SqlException exc)
            {
                if (exc.Message.Contains("ONLYCREATORCANDELETE"))
                    throw new TaskSubTaskValidationException("Only the task creator can delete the task.",
                        SharedEnum.CrudState.Delete,
                        (int)DeleteStatus.ONLYCREATORCANDELETE);

                if (exc.Message.Contains("CURRENTUSERNOTMEMBER"))
                    throw new TaskSubTaskValidationException("User is not a member in the project.",
                        SharedEnum.CrudState.Delete,
                        (int)DeleteStatus.CURRENTUSERNOTMEMBER);

                throw exc;
            }
        }

        #endregion IRepository<_TaskSubTask> Members

        #region "Crud Enums"

        public enum InsertStatus
        {
            TASKNOTFOUND = -1,
            CREATORNOTMEMBER = -2,
            ASSIGNEDNOTMEMBER = -3,
            INVALIDCREATIONUSER = -4,
            INVALIDASSIGNEDUSER = -5,
            SUBTASKNOTVALID = -6
        }

        public enum UpdateStatus
        {
            TASKNOTFOUND = -1,
            ONLYCREATORCANCHANGE = -2,
            LASTCHANGEUSERNOTMEMBER = -3,
            ASSIGNEDNOTMEMBER = -4,
            SUBTASKNOTVALID = -5
        }

        public enum DeleteStatus
        {
            ONLYCREATORCANDELETE = -1,
            CURRENTUSERNOTMEMBER = -2
        }

        #endregion "Crud Enums"
    }
}